﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace converter
{
    public class CommandLine
    {
        // Creates an instance of the type and parses the command line arguments.
        // Command line must contain at leas one RDL file, otherwise an ArgumentException
        // exception will be thrown.
        public CommandLine(string[] args)
        {
            overwrite = false;
            dataSources = new List<string>();
            reports = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);

            ParseArguments(args);

            if (Reports.Count == 0)
            {
                throw new ArgumentException("Command line must contain at least one RDL file.");
            }
        }

        // Gets a value indicating if the output file can be overwritten.
        public bool Overwrite
        {
            get
            {
                return overwrite;
            }
        }

        // Gets a list of datasource file names supplied on the command line.
        public List<string> DataSources
        {
            get
            {
                return dataSources;
            }
        }

        // Gets a list of report definition files supplied on the command line.
        public Dictionary<string, string> Reports
        {
            get
            {
                return reports;
            }
        }

        private void ParseArguments(string[] args)
        {
            if (args == null)
                return;

            // Lists of appropriate file names found on the command line.
            List<string> reportFiles = new List<string>();
            List<string> outputFiles = new List<string>();

            foreach (string arg in args)
            {
                if (arg.StartsWith("-") || arg.StartsWith("/"))
                {
                    // We've got something looking like an argument.
                    // We expect it to be an option or an option followed by ':' and a file name.
                    string option = string.Empty;
                    string fileName = string.Empty;

                    if (arg.Contains(':'))
                    {
                        int index = arg.IndexOf(':');
                        option = arg.Substring(1, index - 1);
                        fileName = arg.Substring(index + 1);
                    }
                    else
                    {
                        option = arg.Substring(1);
                    }

                    switch (option.ToLower())
                    {
                        case "rdl":
                            if (!string.IsNullOrEmpty(fileName))
                            {
                                reportFiles.Add(fileName);
                            }
                            break;

                        case "out":
                            if (!string.IsNullOrEmpty(fileName))
                            {
                                outputFiles.Add(fileName);
                            }
                            break;

                        case "rds":
                            if (!dataSources.Contains(fileName, StringComparer.CurrentCultureIgnoreCase))
                            {
                                dataSources.Add(fileName);
                            }
                            break;

                        case "y":
                            overwrite = true;
                            break;

                        default:
                            // Bad arguments are ignored.
                            break;
                    }
                }
            }

            if (reportFiles.Count == 1)
            {
                // Single report file.
                if (outputFiles.Count == 1)
                {
                    // And single output file. Build direct association.
                    reports[reportFiles[0]] = outputFiles[0];
                }
                else
                {
                    // No output file or multiple output files. Ignore output files and use base name of the report file.
                    reports[reportFiles[0]] = CreateOutputFileName(reportFiles[0]);
                }
            }
            else
            {
                // Multiple report files or no report file. Construct output file names based on report files.
                foreach (string reportFile in reportFiles)
                {
                    if (!reports.ContainsKey(reportFile))
                    {
                        reports[reportFile] = CreateOutputFileName(reportFile);
                    }
                }
            }
        }

        // Creates a file name based on the report file name provided but with DOCX extension.
        private static string CreateOutputFileName(string reportFile)
        {
            int index = reportFile.LastIndexOf('.');
            string outputFile = reportFile.Substring(0, index + 1) + "docx";
            return outputFile;
        }

        private bool overwrite;
        private readonly List<string> dataSources;
        private readonly Dictionary<string, string> reports;
    }
}
